//手写自定义的vue-loader加载器

//fs API: 同步检测文件是否存在
const {
  existsSync,
  mkdirSync,
  readdirSync,
  unlinkSync,
  writeFileSync
} = require('fs');
const {
  resolve
} = require('path');

const templateReg = /\<template\>(.*?)\<\/template\>/,
  scriptReg = /\<script\>(.*?)\<\/script\>/,
  styleReg = /\<style\>(.*?)\<\/style\>/;


//当webpack处理js/vue后缀文件时会执行这个加载器
//这个加载器会返回希望处理后的结果
function vueLoader(source) {

  //打印的是App.vue里写的代码字符串
  /**
   * console.log(source);
   * <template>
      <div>
        <div>
          <img v-if="isShowImg1" class="img" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1111%2F11131Q45604%2F1Q113145604-2-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1649504657&t=2a48eec8e0e23a2192c960e60ce27b7f" />
          <img v-show="isShowImg2" class="img" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1113%2F021620115230%2F200216115230-9-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1649504684&t=b8e0aa845d744916020406fa30d6217e" />
        </div>
        <button @click="showImg1">Show Image 1</button>
        <button @click="showImg2">Show Image 2</button>
      </div>
    </template>

    <script>
    export default {
      name: 'App',
      data () {
        return {
          isShowImg1: true,
          isShowImg2: true
        }
      },
      methods: {
        showImg1 () {
          this.isShowImg1 = !this.isShowImg1;
        },
        showImg2 () {
          this.isShowImg2 = !this.isShowImg2;
        }
      }
    }
    </style>

    <style>
      .img {
        width: 200px;
      }
    </style>
   */

  //去掉字符串里的换行和空格
  const _str = source.replace(/[\r\n]/g, '');

  //获取<template>里的字符串内容
  const template = _str.match(templateReg)[1];

  //获取<script>里的字符串内容
  const script = _str.match(scriptReg)[1];

  //获取<style>里的字符串内容
  const style = _str.match(styleReg)[1];

  //定义一个临时存放的样式文件
  const cssFileName = `__temp/css/__${new Date().getTime()}.css`;

  //写入文件传入地址，和<style>标签的内容，每次打包经过vue-loader，每次写入样式到文件里
  writeFile(cssFileName, style);

  //组装vue单文件组件：
  //将<script>里的字符串内容放入vue文件里的<script>编写区域位置
  //匹配位置 export default { 第一个{
  const vueScript = script.replace(/\{(.*?)/, (node, key) => {
    return `
      { template: '${ template }',
    `;
  });

  // console.log(vueScript);
  /**
   * export default {
      template: '  <div>    <div>      <img v-if="isShowImg1" class="img" src="https://gimg2.baidu.com/ima..." />      <img v-show="isShowImg2" class="img" src="https://gimg2.ba..." />    </div>   <button @click="showImg1">Show Image 1</button>    <button @click="showImg2">Show Image 2</button>  </div>',
      name: 'App',  data () {    return {      isShowImg1: true,      isShowImg2: true    }  },  
      methods: {    showImg1 () {      this.isShowImg1 = !this.isShowImg1;    },    showImg2 () {   this.isShowImg2 = !this.isShowImg2;    }  }}
   */

  const importPath = `import '${`../${cssFileName}`}'`;
  // console.log(importPath);
  //import '../../__temp/css/__1647272226516.css'

  //返回内容包括：
  //import 'xxx.css'; 和 <style>里面定义的样式代码
  //处理好的script字符串内容 返回组件对象
  //将写好css样式的文件引入到html里
  //<style>  .img {    width: 200px;  }</style>
  return `
    ${ importPath };
    ${ vueScript }
  `;
}

//写入文件操作
function writeFile(cssFileName, styleStr) {

  //如果缓存的临时目录不存在时
  //找到最外层的根目录
  if (!existsSync(formatPath('../../__temp'))) {
    //创建__temp目录
    mkdirSync(formatPath('../../__temp'));
    //在__temp目录下创建css目录
    mkdirSync(formatPath('../../__temp/css'));
  }

  //首先清空__tem/css/目录下所有的临时文件
  //读取当前文件夹获取所有文件
  const files = readdirSync(formatPath('../../__temp/css/'));

  //遍历删除每一个文件
  files && files.forEach(file => {
    unlinkSync(formatPath('../../__temp/css/' + file));
  });

  try {
    //将<style>里定义的样式写入文件里
    writeFileSync(formatPath(`../../${cssFileName}`), styleStr);
  } catch (e) {
    console.log(e);
  }

}

//处理为绝对路径
function formatPath(path) {
  //绝对路径
  const abPath = resolve(__dirname, path);
  // console.log(abPath);
  //C:\frontEnd\demo\vue-loader-webpack-vshow-vif-demo\__temp

  return abPath;
}

module.exports = vueLoader;